/* eslint-disable camelcase */
//import {EventTarget,core,Blob,ProgressEvent} from "dhtml-weixin"

import EventTarget from './EventTarget';
import core from './core/index';
import Blob from './Blob';
import TextDecoder from './TextDecoder';
import ProgressEvent from './ProgressEvent';
const {
	Page,
	Base64
} = core;

function readArrayBuffer(size, filePath, resolve) {

	const fs = wx.getFileSystemManager();
	const data = new ArrayBuffer(size);
	fs.open({
		filePath,
		success(res) {

			fs.read({
				fd: res.fd,
				arrayBuffer: data,
				length: size,
				success() {

					fs.close();
					resolve(data);

				}
			});

		},
		fail(ex){
			console.error("readArrayBuffer",ex)
		}
	});

}

function run(cb, mini_object) {

	return new Promise((resolve, reject) => {

		mini_object.success = resolve;
		mini_object.fail = (ex) => {
x
			console.error('[XMLHttpRequest]', ex);
			reject(e);

		};

		cb(Page.wx_request(mini_object));

	});

}

export default class XMLHttpRequest extends EventTarget {

	static get DONE() {

		return 4;

	}
	//////////////////////////////
	constructor() {

		super();
		this._responseType = null; //'text';
		this._responseHeaders = {};

	}

	open(method, url, async = true, user, password) {

		this._method = method;
		this._url = url;
		this._async = async;
		this._user = user;
		this._password = password;

	}

	getResponseHeader(key) {

		return this._responseHeaders[key];

	}
	async send(body) {

		const callback = (res) => {

			this.readyState = XMLHttpRequest.DONE;
			this._status = 200;
			this._responseHeaders = res.header;
			this._data = res.data;
			//console.error(res.data)


			if (this.onload) {

				this.onload.apply(this);

			}

			if (this._all_event_handlers.load) {

				this._all_event_handlers.load.forEach((handler) => {

					handler.apply(this);

				});

			}

			this.dispatchEvent({
				type: 'readystatechange'
			});

		};

		var url = this._url;
		if (url.startsWith('mini:')) {

			this._status = 200;
			const loadStartEvent = {};
			this.dispatchEvent(loadStartEvent);
			if (this.onloadstart) {

				this.onloadstart(loadStartEvent);

			}

			try {

				var data;
				if (this._responseType == 'text') {

					const MINI = 'mini:';
					const text = url.substring(MINI.length);
					data = text;

				} else {

					const BASE64 = 'base64,';
					const base64 = url.substring(url.indexOf(BASE64) + BASE64.length);
					data = Base64.base64ToArrayBuffer(base64);

				}

				callback.call(this, {
					data
				});

			} catch (ex) {

				console.error("XMLHttpRequest",ex);

			}

			return;

		}

		if (url.startsWith('data:')) {

			this._status = 200;
			const loadStartEvent = {};
			this.dispatchEvent(loadStartEvent);
			if (this.onloadstart) {

				this.onloadstart(loadStartEvent);

			}

			try {

				const BASE64 = 'base64,';
				url = url.substring(url.indexOf(BASE64) + BASE64.length);

				const data = Base64.base64ToArrayBuffer(url);

				callback.call(this, {
					header: {},
					data
				});

			} catch (ex) {

				console.error("XMLHttpRequest",ex);

			}

			return;

		}

		if (url.startsWith('blob:')) {

			this._status = 200;
			const loadStartEvent = {};
			this.dispatchEvent(loadStartEvent);
			if (this.onloadstart) {

				this.onloadstart(loadStartEvent);

			}

			try {

				var global = Page.current;
				if (!global) {

					global = Page.getApp();

				}

				const data = global.DataURL[url].array[0];

				callback.call(this, {
					data
				});

			} catch (ex) {

				console.error("XMLHttpRequest",ex);

			}

			return;

		}

		if (url.startsWith('./')) {

			url = url.substring(2);

		}

		if (!url.startsWith('blob:') &&
			!url.startsWith('data:') &&
			!url.startsWith('mini:') &&
			!url.startsWith('http://') &&
			!url.startsWith('https://')) {

			url = (Page.getApp().onekit_path || '') + url;

		}

		this.responseURL = url;
		const mini_object = {
			url,
			method: this._method
		};
		if (this._async) {

			mini_object.success = (res) => {

				//console.error("wx.downloadFile.succes",res)
				const {
					tempFilePath
				} = res;
				readArrayBuffer(
					res.dataLength,
					//this._responseHeaders[ 'Content-Length' ],
					tempFilePath, (data) => {

						callback.call(this, {
							header: res.header,
							data
						});

					});

			};

			mini_object.fail = function(ex){
				console.error("XMLHttpRequest",ex);
			}
			this._task = Page.wx_downloadFile(mini_object);
			this._task.onHeadersReceived(({
				header
			}) => {

				//console.error("wx.downloadFile.onHeadersReceived", header)
				//	console.error(header)
				this._responseHeaders = header;
				this._status = 200;
				//
				const loadStartEvent = {};
				this.dispatchEvent(loadStartEvent);
				if (this.onloadstart) {

					this.onloadstart(loadStartEvent);

				}

			});
			this._task.onProgressUpdate((res) => {

				// console.error("wx.downloadFile.onProgressUpdate",res)
				const length = res.totalBytesWritten;
				const progressEvent = new ProgressEvent('progress', this, true, length, res.totalBytesExpectedToWrite);
				this.dispatchEvent(progressEvent);
				if (this.onprogress) {

					this.onprogress(progressEvent);

				}

			});

		} else {

			try {

				const res = await run((task) => {

					this._task = task;

				}, mini_object);
				callback.call(this, res);

			} catch (ex) {

				console.error("XMLHttpRequest",ex);

			}

		}

	}
	getAllResponseHeaders() {

		var result = '';
		Object.keys(this._responseHeaders).forEach(key => {

			result += `${key}: ${this._responseHeaders[ key ]}\r\n`;

		});
		return result;

	}
	set responseType(responseType) {

		this._responseType = responseType;

	}

	get responseType() {
		return this._responseType;
	}

	get status() {
		return this._status;
	}

	get response() {
		switch (this._responseType) {
			case "text":
				return this.responseText
			case "blob":
				return new Blob(
				[this._data]
        )
        default:
          return this._data
		}
	}

	get responseText() {
		if (typeof this._data != 'string') {
			return new TextDecoder().decode(this._data);
		} else {
			return this._data
		}
	}

	set onload(onload) {

		this._onload = onload;

	}

	get onload() {

		return this._onload;

	}

	set onloadstart(onloadstart) {

		this._onloadstart = onloadstart;

	}
	get onloadstart() {

		return this._onloadstart;

	}

	set onprogress(onprogress) {

		this._onprogress = onprogress;

	}
	get onprogress() {

		return this._onprogress;

	}

	set onerror(onerror) {

		this._onerror = onerror;

	}

	get onerror() {

		return this._onerror;

	}

}
